export type O1 = { a: string; b: number };
type O2 = { c: number; d: string };

let o1: O1 = { a: "ab", b: 333 };
let o2: O2 = { c: 1, d: "dfd" };

type CrosType<T> = T extends object ? T : never;

function cross<T, U>(obj1: CrosType<T>, obj2: CrosType<U>): T & U;
function cross<T, U, Z>(
  obj1: CrosType<T>,
  obj2: CrosType<U>,
  obj3: CrosType<Z>
): T & U & Z;

function cross<T, U, Z>(
  obj1: CrosType<T>,
  obj2: CrosType<U>,
  obj3?: CrosType<Z>
): T & U & Z {
  const combine = {} as T & U & Z;
  union(combine, obj1);
  union(combine, obj2);
  union(combine, obj3);

  return combine;
}

function union(combine: any, curobj: any) {
  for (const k in curobj) combine[k] = curobj[k];
  return combine;
}

console.log(cross(o1, o2));

export {};
